package com.googlecode.alfrescocachingserver.model.schemas.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.sax.SAXSource;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

import com.googlecode.alfrescocachingserver.model.schemas.ServerCacheConfigs;

/**
 * Process XML files.
 */
public class SchemaUtils
{
    protected static final Logger LOG = LoggerFactory.getLogger(SchemaUtils.class);

    private static SchemaUtils instance = null;
    private static JAXBContext context = null;

    private static final Class<?>[] JAXB_CLASSES = new Class[] {
            ServerCacheConfigs.class,
    };

    /**
     * Constructor
     */
    protected SchemaUtils() throws JAXBException
    {
        // default singleton constructor
        
        try
        {
            context = JAXBContext.newInstance(JAXB_CLASSES);
        }
        catch (JAXBException e)
        {
            LOG.error(e.toString(), e);

            throw e;
        }
    }

    /**
     * gets the instance of the SchemaUtils
     * 
     * @return SchemaUtils
     * @throws JAXBException
     *             JAXBException
     */
    public static SchemaUtils getInstance() throws JAXBException
    {
        if (instance == null)
        {
            instance = new SchemaUtils();
         
        }

        return instance;
    }

    /**
     * Unmarshalls the xml to ServerCacheConfigs
     * 
     * @param xml
     *            xml
     * @return ServerCacheConfigs
     * @throws JAXBException
     *             JAXBException
     * @throws SAXException 
     */
    public ServerCacheConfigs getServerCacheConfigs(final InputStream inputStream) throws JAXBException, SAXException
    {
        // Create an XMLReader to use with our filter
        XMLReader reader = XMLReaderFactory.createXMLReader();

        NamespaceFilter namespaceFilter = new NamespaceFilter("http://www.googlecode.com/alfrescocachingserver/schemas", true);
        namespaceFilter.setParent(reader);

        // Prepare the input, in this case a java.io.File (output)
        InputSource inputSource = new InputSource(inputStream);
        
        //Create a SAXSource specifying the filter
        SAXSource source = new SAXSource(namespaceFilter, inputSource);
        
        final Unmarshaller unmarshaller = context.createUnmarshaller();
        return (ServerCacheConfigs) unmarshaller.unmarshal(source);
    }

    /**
     * Unmarshalls the xml to ServerCacheConfigs
     * 
     * @param xml
     *            xml
     * @return ServerCacheConfigs
     * @throws JAXBException
     *             JAXBException
     * @throws FileNotFoundException 
     * @throws SAXException 
     */
    public ServerCacheConfigs getServerCacheConfigs(final File xmlFile)
            throws JAXBException, FileNotFoundException, SAXException
    {
        FileInputStream fileInputStream = null;
        
        try
        {
            fileInputStream = new FileInputStream(xmlFile);
            
            return getServerCacheConfigs(fileInputStream);
        }
        finally
        {
            IOUtils.closeQuietly(fileInputStream);
        }
    }

    /**
     * Unmarshalls the xml to ServerCacheConfigs
     * 
     * @param url
     *            URL
     * @return ServerCacheConfigs
     * @throws JAXBException
     *             JAXBException
     * @throws IOException 
     * @throws SAXException 
     */
    public ServerCacheConfigs getServerCacheConfigs(final URL url)
            throws IOException, JAXBException, SAXException
    {
        InputStream inputStream = null;
        
        try
        {
            inputStream = url.openStream();
            
            return getServerCacheConfigs(inputStream);
        }
        finally
        {
            IOUtils.closeQuietly(inputStream);
        }
    }
}
